package com.rex.saas.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.rex.saas.bean.DeviceBasicData;
import com.rex.saas.bean.request.AddOtaInfoRequest;
import com.rex.saas.constants.ApiConstant;
import com.rex.saas.constants.Constants;
import com.rex.saas.db.entity.PaasGatewayDeviceRelation;
import com.rex.saas.db.entity.SaasOtaInfo;
import com.rex.saas.db.mapper.SaasOtaInfoMapper;
import com.rex.saas.enums.StatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class OtaService {
    @Autowired
    private SaasOtaInfoMapper saasOtaInfoMapper;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private RexolarApiClient rexolarApiClient;


    public List<SaasOtaInfo> queryOtaInfoByName(String categoryName, String modelId, String version, String tenantId) {
        LambdaQueryWrapper<SaasOtaInfo> queryWrapper = new LambdaQueryWrapper<SaasOtaInfo>();
        queryWrapper.eq(SaasOtaInfo::getCategoryName, categoryName);
        queryWrapper.eq(SaasOtaInfo::getModelId, modelId);
        queryWrapper.eq(SaasOtaInfo::getVersion, version);
        queryWrapper.eq(SaasOtaInfo::getTenantId, tenantId);
        queryWrapper.eq(SaasOtaInfo::getStatus, StatusEnum.ENABLE.getCode());
        return saasOtaInfoMapper.selectList(queryWrapper);
    }

    public boolean addOtaInfo(AddOtaInfoRequest addOtaInfoRequest, String tenantId) {
        SaasOtaInfo saasOtaInfo = new SaasOtaInfo();
        BeanUtils.copyProperties(addOtaInfoRequest, saasOtaInfo);
        saasOtaInfo.setTenantId(tenantId);
        return saasOtaInfoMapper.insert(saasOtaInfo) == 1;
    }

    public SaasOtaInfo latest(String name, String modelId, Integer type) {
        LambdaQueryWrapper<SaasOtaInfo> queryWrapper = new LambdaQueryWrapper<SaasOtaInfo>();
        queryWrapper.eq(SaasOtaInfo::getCategoryName, name);
        queryWrapper.eq(SaasOtaInfo::getType, type);
        if(StringUtils.isNotBlank(modelId)){
            queryWrapper.eq(SaasOtaInfo::getModelId, modelId);
        }
        queryWrapper.eq(SaasOtaInfo::getStatus, StatusEnum.ENABLE.getCode());
        queryWrapper.orderByDesc(SaasOtaInfo::getGmtCreated);
        List<SaasOtaInfo> list = saasOtaInfoMapper.selectList(queryWrapper);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    public boolean updateGwOta(List<String> deviceNames, SaasOtaInfo saasOtaInfo, String token) {
        for(String deviceName : deviceNames){
            DeviceBasicData deviceBasicData =  rexolarApiClient.getDeviceByDeviceName(deviceName, token);
            if(deviceBasicData==null){
                log.error("updateGwOta core deviceName is not exist, deviceName:{}", deviceName);
                continue;
            }

            HashMap<String, Object> dataMap = new HashMap();
            dataMap.put(Constants.Version, "1.0");
            dataMap.put("VendorCode", "Rexense");
            String time = String.valueOf(System.currentTimeMillis());
            dataMap.put("Timestamp", time);
            dataMap.put("Seq", deviceName + "-" + time);
            dataMap.put("DeviceId", deviceName);
            dataMap.put("FunctionCode", "UpgradeGwApp");
            HashMap<String, String> payloadMap = new HashMap<>();
            payloadMap.put(Constants.Version, saasOtaInfo.getVersion());
            payloadMap.put("URL", saasOtaInfo.getDownloadUrl());
            payloadMap.put("MD5", saasOtaInfo.getMd5());
            payloadMap.put("Size", saasOtaInfo.getSize());
            payloadMap.put("Type", String.valueOf(saasOtaInfo.getType()));
            dataMap.put("Payload", payloadMap);
            boolean flag = rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
            if(flag){
                log.error("updateGwOta error, deviceName:{}", deviceName);
                return false;
            }

        }
        return true;
    }

    public boolean updateSubDeviceOta(List<String> deviceNames, SaasOtaInfo saasOtaInfo, String token) {
        Map<String, List<String>> gwDeviceMap = new HashMap<>();
        for(String deviceName : deviceNames){
            PaasGatewayDeviceRelation paasGatewayDeviceRelation = deviceService.getGwByDevcieName(deviceName);
            if(paasGatewayDeviceRelation==null){
                log.error("updateSubDeviceOta gw is not exist, deviceName:{}", deviceName);
                continue;
            }
            List<String> subList = gwDeviceMap.get(paasGatewayDeviceRelation.getGwId());
            if(CollectionUtils.isEmpty(subList)){
                subList = new ArrayList<>();
                subList.add(deviceName);
                gwDeviceMap.put(paasGatewayDeviceRelation.getGwId(), subList);
            }else {
                subList.add(deviceName);
            }
        }

        for(Map.Entry<String, List<String>> entry : gwDeviceMap.entrySet()){
            DeviceBasicData gw = rexolarApiClient.getDeviceById(entry.getKey(), token);
            if(gw==null){
                log.error("updateSubDeviceOta gw DeviceBasicData is not exist, deviceName:{}", entry.getKey());
                continue;
            }
            HashMap<String, Object> dataMap = new HashMap();
            dataMap.put(Constants.Version, "1.0");
            dataMap.put("VendorCode", "Rexense");
            String time = String.valueOf(System.currentTimeMillis());
            dataMap.put("Timestamp", time);
            dataMap.put("Seq", gw.getName() + "-" + time);
            dataMap.put("DeviceId", gw.getName());
            dataMap.put("FunctionCode", "OTAUpgradeDev");
            HashMap<String, Object> payloadMap = new HashMap<>();
            payloadMap.put(Constants.Version, saasOtaInfo.getVersion());
            payloadMap.put("URL", saasOtaInfo.getDownloadUrl());
            payloadMap.put("MD5", saasOtaInfo.getMd5());
            payloadMap.put("Size", saasOtaInfo.getSize());
            payloadMap.put("DeviceIds", entry.getValue());
            payloadMap.put("Type", String.valueOf(saasOtaInfo.getType()));
            dataMap.put("Payload", payloadMap);
            boolean flag = rexolarApiClient.updateDeviceAttributes(entry.getKey(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
            if(flag){
                log.error("updateSubDeviceOta error, deviceNames:{}", entry.getValue());
                return false;
            }
        }
        return true;
    }

    public boolean updateDeviceOta(List<String> deviceNames, SaasOtaInfo saasOtaInfo, String token) {
        for(String deviceName : deviceNames){
            DeviceBasicData deviceBasicData =  rexolarApiClient.getDeviceByDeviceName(deviceName, token);
            if(deviceBasicData==null){
                log.error("updateDeviceOta core deviceName is not exist, deviceName:{}", deviceName);
                continue;
            }

            HashMap<String, Object> dataMap = new HashMap();
            dataMap.put(Constants.Version, "1.0");
            dataMap.put("VendorCode", "Rexense");
            String time = String.valueOf(System.currentTimeMillis());
            dataMap.put("Timestamp", time);
            dataMap.put("Seq", deviceName + "-" + time);
            dataMap.put("DeviceId", deviceName);
            dataMap.put("FunctionCode", "OTAUpgradeDCDev");
            HashMap<String, String> payloadMap = new HashMap<>();
            payloadMap.put(Constants.Version, saasOtaInfo.getVersion());
            payloadMap.put("URL", saasOtaInfo.getDownloadUrl());
            payloadMap.put("MD5", saasOtaInfo.getMd5());
            payloadMap.put("Size", saasOtaInfo.getSize());
            payloadMap.put("Type", String.valueOf(saasOtaInfo.getType()));
            dataMap.put("Payload", payloadMap);
            boolean flag = rexolarApiClient.updateDeviceAttributes(deviceBasicData.getCoreId(), ApiConstant.SHARED_SCOPE, JSON.toJSONString(dataMap), token);
            if(!flag){
                log.error("updateDeviceOta error, deviceName:{}", deviceName);
                return false;
            }

        }
        return true;
    }
}
